import os
import sys
import hashlib
import windnd
from threading import Thread
from tkinter import *
from tkinter.scrolledtext import ScrolledText


busy_now = False


def compute_file_hash(file_path, hash_alg):
    # 保存整个文件的摘要
    if hash_alg == 1:
        hash_all = hashlib.md5()
    elif hash_alg == 2:
        hash_all = hashlib.sha1()
    elif hash_alg == 3:
        hash_all = hashlib.sha256()
    else:
        return None

    filelen = os.path.getsize(file_path)
    recvlen = 0
    chunk_size = 1024*1024

    # 读文件数据，计算摘要
    with open(file_path, 'rb', buffering=0) as fd:
        while filelen > recvlen:
            rs = filelen - recvlen
            if rs > chunk_size:
                rs = chunk_size
            # 一次最多读分块大小的数据
            buf = fd.read(rs)
            if not buf:
                break
            # 累加当前分块中已读数据长度
            recvlen += len(buf)
            hash_all.update(buf)

    if filelen != recvlen:
        return None

    # 整个文件的摘要
    digest = hash_all.hexdigest().upper()
    return digest, str(filelen)


def thread_work(filelist, hash_alg):
    global busy_now

    res = ''
    for f in filelist:
        d, l = compute_file_hash(f, hash_alg)
        res += f + '\n'
        res += '    Size: ' + l + '\n'
        if hash_alg == 1:
            res += '     MD5: '
        elif hash_alg == 2:
            res += '    SHA1: '
        elif hash_alg == 3:
            res += ' SHA-256: '
        res += d + '\n\n'

    showMsg(res)
    busy_now = False


def showMsg(txt):
    Edit1.configure(state='normal')
    Edit1.delete(1.0, END)
    Edit1.insert(1.0, '\n' + txt)
    Edit1.configure(state='disabled')
    

def dragged_files(files):
    global busy_now

    if busy_now:
        return

    filelist = []
    for file in files:
        f = file.decode('gbk')
        if not os.path.isfile(f):
            showMsg('您选择的对象不是文件！')
            return
        filelist.append(f)

    busy_now = True
    showMsg('计算中......')
    t = Thread(target=thread_work, args=[filelist, radio_val.get()])
    t.run() # 还不能用start()启动新线程，因为现在线程中不能操作UI了，会崩溃


root = Tk()
root.title('Drag Hash Tool')
windnd.hook_dropfiles(root, func=dragged_files)

radio_val = IntVar()
radio_val.set(3)
Radiobutton(root, text="MD5", variable=radio_val,
            value=1, pady=8).grid(row=1, column=1)
Radiobutton(root, text="SHA1", variable=radio_val,
            value=2, pady=8).grid(row=1, column=2)
Radiobutton(root, text="SHA-256", variable=radio_val,
            value=3, pady=8).grid(row=1, column=3)

Edit1 = ScrolledText(root, width=80, height=20, padx=8, pady=8)
Edit1.grid(row=2, column=1, columnspan=3)
showMsg('请拖放文件......')

root.mainloop()
